package cn.huijielong.config;


import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import cn.huijielong.common.annotation.NoAuthFilter;
import cn.huijielong.common.exception.VSException;


@Component
public class ReLoadShiroFilter implements ApplicationContextAware{
	
	@Autowired
	private ShiroFilterFactoryBean shiroFilter;
	
	private final static Logger logger = LoggerFactory.getLogger(ReLoadShiroFilter.class); 
	//@PostConstruct
	public void intiPermission() {
		logger.debug("initialize shiro permission success...");
	}
	
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) 
			throws BeansException {
		
		Map<String, String> newfilterChainDefinitionMap = new HashMap<>();
		//获取所有controller bean
		Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(RestController.class);
		for (Map.Entry<String, Object> entry:beansWithAnnotation.entrySet()) {
			String classReqMappingValue = null;
			Object controllerObj=entry.getValue();
			String className=controllerObj.getClass().getName();
			Class<? extends Object> clazz = null;
			int k = className.indexOf("$");
			if(k<0) {
				 clazz= controllerObj.getClass();
			}else {
				try {
					clazz= Class.forName(className.substring(0,k));
				} catch (ClassNotFoundException e) {
					
					e.printStackTrace();
				}
			}
			
			//获取类上requestMapping的value
			RequestMapping classReq = clazz.getAnnotation(RequestMapping.class);
			if(classReq!=null && classReq.value()!=null && classReq.value().length>0) {
				classReqMappingValue= classReq.value()[0];
			}
			//类中所有公共方法
			Method[] methods = clazz.getMethods();
			for(int i=0;methods!=null && i<methods.length;i++) {
				NoAuthFilter noOAuth2 = methods[i].getAnnotation(NoAuthFilter.class);
				if(noOAuth2==null){
					continue;
				}
				//处理包含noOAuth2注解的方法
				if(noOAuth2!=null) {
					RequestMapping methoReq = methods[i].getAnnotation(RequestMapping.class);
					if(methoReq!=null && methoReq.value()!=null && methoReq.value().length>0 ) {
						String methodReqMappingValue=null;
						String requestMappings = null;
						//处理方法上的requestMapping 处理get请求
						int j = methoReq.value()[0].indexOf("{");
						if(j>=0) { 
							methodReqMappingValue=methoReq.value()[0].substring(0, j)+"**";
						}else {
							methodReqMappingValue=methoReq.value()[0]+"/**";
						}
						//拼接类和方法上的requestMapping
						if(classReqMappingValue!=null) {
							requestMappings = classReqMappingValue+methodReqMappingValue;
						}else {
							requestMappings=methodReqMappingValue;
						}
						if(requestMappings!=null) {
							newfilterChainDefinitionMap.put(requestMappings,"anon");//anon为不做token验证
						}
					}else {
						throw new VSException("method："+methods[i].getName()+"注解requestMapping值为空");
					}
				}
			}
		}
		createChain(newfilterChainDefinitionMap);
		//System.out.println("mapping=========================="+filterChainDefinitionMap);
	}

	public void createChain(Map<String, String> newfilterChainDefinitionMap) {
		AbstractShiroFilter filter = null;
		 
		try {
			filter = (AbstractShiroFilter) shiroFilter.getObject();
		} catch (Exception e) {
			
		}

		// 获取过滤管理器
		PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) filter
				.getFilterChainResolver();
		DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();

		Map<String, String> newDefinitions=new LinkedHashMap<>();
		newDefinitions.putAll(shiroFilter.getFilterChainDefinitionMap());
		newDefinitions.putAll(newfilterChainDefinitionMap);
		String oauth2=newDefinitions.remove("/**");
		if (oauth2!=null) {
			newDefinitions.put("/**", oauth2);
		}
		String definitions=newDefinitions.toString().replaceAll("\\{", "").replaceAll("\\}", "").replaceAll(",", "\n");
		
		//Map<String,String> definitions=new HashMap<>();
		//definitions.putAll(filter.getFilterChainDefinitionMap());
		manager.getFilterChains().clear();
		shiroFilter.getFilterChainDefinitionMap().clear();
		
		
		// 重新构建生成
		shiroFilter.setFilterChainDefinitions(definitions);

		for (Map.Entry<String, String> entry : newDefinitions.entrySet()) {
			String url = entry.getKey();
			String chainDefinition = entry.getValue().trim().replace(" ", "");
			manager.createChain(url, chainDefinition);
		}
		
	}
}
